import log from "@/common/app/log.js";
import utils from "@/common/app/utils.js";
import tool from "./tool.js";
import axios from "axios";

const serverConfig = utils.getServerConfig() || {};
const requestInstance = axios.create({
  // 请求超时时间
  timeout: (serverConfig.timeout || 60) * 1000,
  // 默认请求方式为：POST
  method: "POST",
  // 项目baseURL
  baseURL: serverConfig.serverUrl,
});

// 将所有的批次请求放入一个全局列表中，当页面发生跳转时，将所有未完成的请求取消掉
window.axiosPromiseArr = [];
window.axiosKeyArr = [];
// 请求拦截处理
/**
 * 请求数据的方法
 * @param {Object}  options 请求参数对象
 *                  {String}  url: 接口地址
 *                  {String}  method: http接口请求方式：GET、POST、DELETE、PUT、UPDATE
 *                  {any}     data: 接口请求数据，任意类型
 *                  {Object}  headers: 接口请求消息头参数配置
 *                  {String}  message: 接口错误的提示消息，如果该字段不为空，则当请求失败时，会在接口调用处处理错误消息的展示，业务侧则不需要进行消息提示处理
 *                  {Boolean} isMock: 当前接口是否需要使用本地模拟桩数据
 *                  {Boolean} unneedLog: 不需要打印接口日志，如果不传入该参数，默认会打印接口日志，如果某个接口响应的结果数据太大，该参数配置为true，不打印接口日志
 */
requestInstance.interceptors.request.use(
  (axiosConfig) => {
    // ******************* 请求参数封装 BEGIN *******************
    log.debug("开始接口请求，接口请求参数为：", axiosConfig);
    if (axiosConfig.isRefresh) {
      log.debug("当前接口请求是刷新用户Token的操作");
    }
    // ************** 通过公共方法根据配置及参数获取封装的请求参数 **************
    let options = tool.buildAppBaseConfig(axiosConfig);
    options = tool.buildAppCustomeConfig(options);
    Object.assign(axiosConfig, options);
    // ************** 通过公共方法根据配置及参数获取封装的请求参数 **************
    // ******************* 请求参数封装 END *******************

    // ******************* 将所有请求均存放在全局对象中，在页面切换时，终止请求 BEGIN *******************
    const configKey = axiosConfig.url + "_____" + new Date().getTime();
    axiosConfig.cancelToken = new axios.CancelToken((cancel) => {
      window.axiosPromiseArr.push({ cancel });
      window.axiosKeyArr.push(configKey);
    });
    axiosConfig.configKey = configKey;
    // ******************* 将所有请求均存放在全局对象中，在页面切换时，终止请求 END *******************
    return axiosConfig;
  },
  (error) => {
    // Do something with request error
    return Promise.reject(error);
  }
);

// 响应拦截处理
requestInstance.interceptors.response.use(
  (response) => {
    // 请求响应完成后，将当当前对应的请求全局保存的信息从axiosKeyArr和axiosPromiseArr中移除
    const reqIndex = window.axiosKeyArr.indexOf(response.config.configKey);
    window.axiosKeyArr.splice(reqIndex, 1);
    window.axiosPromiseArr.splice(reqIndex, 1);

    const options = response.config;
    let result = tool.proccessResponse(response, options);
    if (result.code === 0) {
      // 有些接口响应消息过大，不进行结果日志打印，可以通过接口进行配置
      if (!options.unneedLog) {
        log.info(
          "接口请求成功，接口[" + options.url + "]的响应结果为：",
          result
        );
      } else {
        log.info("接口请求成功，接口地址为：" + options.url);
      }
      result.success = tool.isResponseSuccess(result);
    } else {
      // 所有请求失败也执行resolve方法，封装统一的错误消息给业务接口调用处
      // 只有当存在返回消息时，才返回错误消息
      log.error(
        "fetch接口请求失败，请求url为：",
        options.url,
        "；请求参数为：",
        options.data,
        "；错误码为：",
        result.code,
        "；错误消息为：",
        result.message
      );
    }
    if (!result.message) {
      result.message = tool.getResponseMessage(result, options);
    }
    return result;
  },
  (error) => {
    // Do something with response error
    // 请求失败，执行请求失败的函数reject
    return Promise.resolve(error);
  }
);

export default requestInstance;
